import { VisualDataCloud } from '@/common/render';
import RenderProto from '@/common/render/model/proto';
import { ModelTreeObjectType } from '@/common/types';
import { DocumentUtils, getQueryParam, QueryParamKeys } from '@amcax/base';
import { SocketEventHandler, SocketStatusListener } from 'nextcae-base';
import { BaseSocket } from './baseSocket';

/**
 * 解析渲染的protobuf二进制数据
 * @param uint8 二进制数据
 * @returns
 */
function decodeRenderProtobuf(uint8: Uint8Array): RenderProto.RenderResponse {
  const rsp = RenderProto.RenderResponse.decode(uint8);
  // hack protobuf 如果code是 0 就会被忽略，这里判断一下
  if (rsp && !rsp.code) {
    rsp.code = 0;
  }
  return rsp;
}

/**
 * 设置监听、基础接口等功能类
 */
export class Basic extends BaseSocket {
  async registerEventHandler(eventHandler: SocketEventHandler) {
    const engine = await BaseSocket.getEngine();
    engine?.registerEventHandler(eventHandler);
  }

  async unregisterEventHandler(eventHandler: SocketEventHandler) {
    const engine = await BaseSocket.getEngine();
    engine?.unregisterEventHandler(eventHandler);
  }

  /**
   * 添加监听Socket服务的状态（主要是关闭时）
   * @param listener
   */
  async addStatusListener(listener: SocketStatusListener) {
    const engine = await BaseSocket.getEngine();
    engine?.addStatusListener(listener);
  }

  /**
   * 移除监听Socket服务
   */
  async removeStatusListener(listener: SocketStatusListener) {
    const engine = await BaseSocket.getEngine();
    engine?.removeStatusListener(listener);
  }

  async stop() {
    const engine = await BaseSocket.getEngine();
    engine?.stop();
  }

  /**
   * 设置WebSocket Engine的二进制解码函数
   */
  async setDecodeBinaryDataFunc() {
    const engine = await BaseSocket.getEngine();
    engine?.setDecodeBinaryDataFunc(decodeRenderProtobuf);
  }

  /**
   * 打开文档
   */
  async openDocument(): Promise<void> {
    const documentVersion = getQueryParam<string>(QueryParamKeys.VERSION);
    return await this.execCmd({
      c: 'shape.OpenDocument',
      readonly: DocumentUtils.isReadOnly(),
      version: documentVersion,
    });
  }

  /**
   * 导入几何（step）/网格（obj/stl）到文档
   */
  async import(path: string) {
    return await this.execCmd({
      c: 'shape.Import',
      t: path,
    });
  }

  /**
   * 导出几何（step）/网格（obj）
   */
  async export(params?: {
    path: string; // s3或本地路径
    object: string[]; // 需要导出的对象id
  }) {
    return await this.execCmd({ c: 'shape.Export', a: params });
  }

  /**
   * 获取模型树信息
   */
  async getObjects(): Promise<ModelTreeObjectType[]> {
    const data: { objects: ModelTreeObjectType[] } = await this.execCmd({
      c: 'shape.GetObjects',
    });
    return data?.objects;
  }

  /**
   * 获取渲染数据
   * @param objects shape（id）数组
   */
  async renderData(objects?: string[]): Promise<VisualDataCloud[]> {
    return await this.execCmd({
      c: 'shape.GetVisualData',
      a: { objects, mode: 'protobuf' },
    });
  }

  /**
   * 设置显隐
   */
  async setVisibility(objects: string[], visible: boolean) {
    return await this.execCmd({
      c: 'shape.SetVisibility',
      a: { objects, visible },
    });
  }

  /**
   * 删除对象
   */
  async deleteObjects(objects: string[]) {
    return await this.execCmd({
      c: 'shape.Delete',
      a: { objects },
    });
  }
}
